<?php

namespace Sjj\Eloquent\Concerns;

use Illuminate\Support\Collection;
use Sjj\Eloquent\ViewModel;

trait HasRelationships
{
	/**
	 * The loaded relationships for the model.
	 *
	 * @var array
	 */
	protected $relations = [];

	/**
	 * Define a one-to-one relationship.
	 *
	 * @param string $relation
	 * @param mixed $viewModel
	 */
	public function hasOne($relation, $viewModel)
	{
		$this->setRelation($relation, $viewModel);
	}

	/**
	 * Define an inverse one-to-one or many relationship.
	 *
	 * @param string $relation
	 * @param ViewModel $viewModel
	 */
	public function belongsTo(string $relation, ViewModel $viewModel)
	{
		$this->setRelation($relation, $viewModel);
	}

	/**
	 * Define a one-to-many relationship.
	 *
	 * @param string $relation
	 * @param \Illuminate\Support\Collection|ViewModel[] $viewModels
	 */
	public function hasMany(string $relation, \Illuminate\Support\Collection $viewModels)
	{
		$this->setRelation($relation, $viewModels);
	}

	/**
	 * Get all the loaded relations for the instance.
	 *
	 * @return array
	 */
	public function getRelations()
	{
		return $this->relations;
	}

	/**
	 * Get a specified relationship.
	 *
	 * @param string $relation
	 * @return mixed
	 */
	public function getRelation($relation)
	{
		return $this->relations[$relation];
	}

	/**
	 * Determine if the given relation is loaded.
	 *
	 * @param string $key
	 * @return bool
	 */
	public function relationLoaded($key)
	{
		return array_key_exists($key, $this->relations);
	}

	/**
	 * Set the given relationship on the model.
	 *
	 * @param string $relation
	 * @param mixed|ViewModel|Collection|ViewModel[] $viewModel
	 * @return $this
	 */
	public function setRelation($relation, $viewModel)
	{
		$this->relations[$relation] = $viewModel;

		$this->{$relation} = $viewModel;

		return $this;
	}

	/**
	 * Unset a loaded relationship.
	 *
	 * @param string $relation
	 * @return $this
	 */
	public function unsetRelation($relation)
	{
		unset($this->relations[$relation]);

		return $this;
	}

	/**
	 * Set the entire relations array on the model.
	 *
	 * @param array $relations
	 * @return $this
	 */
	public function setRelations(array $relations)
	{
		$this->relations = $relations;

		return $this;
	}
}
